#ifndef TIME_WHEEL_TIMER
#define TIME_WHEEL_TIMER

#include <iostream>
#include <functional>
#include <time.h>
#include <netinet/in.h>

const int BUFFER_SIZE = 64;
class timeWheel_Timer;
struct clientData {
    sockaddr_in address;
    int sockFd;
    char buf[BUFFER_SIZE];
    timeWheel_Timer* timer;
};

struct timeWheel_Timer {
public:
    int rotation;   // 转多少圈
    int timeSlot;   // 哪个槽上
    using cbFunc = std::function<void(clientData*)>;
    cbFunc cb;
    clientData* userData;
    timeWheel_Timer* next;
    timeWheel_Timer* prev;

    timeWheel_Timer(int rot, int ts)
    : prev(nullptr), next(nullptr), rotation(rot), timeSlot(ts)
    {}
};

class timeWheel {
private:
    static const int N = 60;
    static const int SI = 1;
    timeWheel_Timer* slots[N];
    int curSlot;

public:
    timeWheel()
    : curSlot(0)
    {
        for(int i = 0; i < N; ++i) {
            slots[i] = nullptr;
        }
    }
    ~timeWheel() {
        for(int i = 0; i < N; ++i) {
            timeWheel_Timer* tmp = slots[i];
            while(tmp) {
                slots[i] = tmp->next;
                delete tmp;
                tmp = slots[i];
            }
        }
    }

    timeWheel_Timer* addTimer(int timeout) {
        if(timeout < 0) {
            return nullptr;
        }
        int ticks = 0;
        if(timeout < SI) {
            ticks = 1;
        }
        else {
            ticks = timeout / SI;
        }
        int rotation = ticks / N;
        int ts = (curSlot + (ticks % N) % N);
        timeWheel_Timer* timer = new timeWheel_Timer(rotation, ts);

        if(!slots[ts]) {
            cout << "add timer, rotation is " << rotation << ", ts is " << ts 
                 << ", cutSlot is " << curSlot << endl;
            slots[ts] = timer;
        }
        else {
            timer->next = slots[ts];
            slots[ts]->prev = timer;
            slots[ts] = tiemr;
        }
        return timer;
    }

    void delTimer(timeWheel_Timer* timer) {
        if(!timer) {
            return;
        }
        int ts = timer->timeSlot;
        if(timer == slots[ts]) {
            slots[ts] = slots[ts] ->next;
            if(slots[ts]) {
                slots[ts]->prev = nullptr;
            }
            delete timer;
        }
        else {
            timer->prev->next = timer->next;
            if(timer->next) {
                timer->next->prev = timer->prev;
            }
            delete timer;
        }
    }

    void tick() {
        timeWheel_Timer* tmp = slots[curSlot];
        cout << "current slot is " << curSlot << endl;
        while(tmp) {
            cout << "tick the timer once" << endl;
            if(tmp->rotation > 0) {
                tmp->rotation--;
                tmp = tmp->next;
            }
            else {
                tmp->cb(tmp->userData);
                if(tmp == slots[curSlot]) {
                    cout << "delete header int curSlot" << endl;
                    delTimer(tmp);
                    tmp = slots[curSlot];
                }
                else {
                    tmp->prev->next = tmp->next;
                    if(tmp->next) {
                        tmp->next->prev = tmp->prev;
                    }
                    timeWheel_Timer* tmp2 = tmp->next;
                    delete tmp;
                    tmp = tmp2;
                }
            }
        }
        curSlot = ++curSlot % N;
    }
};

#endif 